/*
* Copyright 2013 Fusepool Project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.fusepool.datalifecycle.core;
import java.security.AccessController;
import java.security.AllPermission;
import java.util.Iterator;
import java.util.concurrent.locks.Lock;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.clerezza.jaxrs.utils.RedirectUtil;
import org.apache.clerezza.jaxrs.utils.TrailingSlash;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.Triple;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.LockableMGraph;
import org.apache.clerezza.rdf.core.access.TcManager;
import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
import org.apache.clerezza.rdf.core.impl.TripleImpl;
import org.apache.clerezza.rdf.core.serializedform.Serializer;
import org.apache.clerezza.rdf.ontologies.RDF;
import org.apache.clerezza.rdf.ontologies.RDFS;
import org.apache.clerezza.rdf.utils.GraphNode;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.stanbol.commons.indexedgraph.IndexedMGraph;
import org.apache.stanbol.commons.web.viewable.RdfViewable;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.fusepool.datalifecycle.ontologies.DLC;
@Component
@Property(name = "javax.ws.rs", boolValue = true)
@Service(Object.class)
@Path("pipesadmin")
public class PipesAdmin {
/**
* This service allows accessing and creating persistent triple collections
*/
@Reference
private TcManager tcManager;
@Reference
private Serializer serializer;
@Reference
private DataSetFactory dataSetFactory;
@Reference
private DlcGraphProvider dlcGraphProvider;
/**
* Using slf4j for normal logging
*/
private static final Logger log = LoggerFactory.getLogger(PipesAdmin.class);
/**
* This method return an RdfViewable, this is an RDF serviceUri with
* associated presentational information.
*/
@GET
public RdfViewable serviceEntry(@Context final UriInfo uriInfo,
@QueryParam("url") final UriRef url,
@HeaderParam("user-agent") String userAgent) throws Exception {
//this maks sure we are nt invoked with a trailing slash which would affect
//relative resolution of links (e.g. css)
TrailingSlash.enforcePresent(uriInfo);
final String resourcePath = uriInfo.getAbsolutePath().toString();
if (url != null) {
String query = url.toString();
log.info(query);
}
//The URI at which this service was accessed, this will be the
//central serviceUri in the response
final UriRef serviceUri = new UriRef(resourcePath);
//the in memory graph to which the triples for the response are added
final MGraph responseGraph = new IndexedMGraph();
Lock rl = getDlcGraph().getLock().readLock();
rl.lock();
try {
responseGraph.addAll(getDlcGraph());
//Add the size info of the graphs of all the datasets
addGraphsSize(responseGraph);
} finally {
rl.unlock();
}
//This GraphNode represents the service within our result graph
final GraphNode node = new GraphNode(serviceUri, responseGraph);
node.addProperty(DLC.graph, DlcGraphProvider.DATA_LIFECYCLE_GRAPH_REFERENCE);
//What we return is the GraphNode to the template with the same path and name
return new RdfViewable("PipesAdmin", node, PipesAdmin.class);
}
/**
* Add the size of the graphs within each dataset/pipe to the rdf data for visualization
*/
private void addGraphsSize(MGraph responseGraph){
Iterator<Triple> datasets = getDlcGraph().filter(DlcGraphProvider.DATA_LIFECYCLE_GRAPH_REFERENCE, DLC.pipe, null);
while(datasets.hasNext()){
final UriRef datasetRef = (UriRef) datasets.next().getObject();
final DataSet dataSet = dataSetFactory.getDataSet(datasetRef);
// add source graph size
int sourceGraphSize = dataSet.getSourceGraph().size();
responseGraph.add(new TripleImpl(dataSet.getSourceGraphRef(), DLC.size, new PlainLiteralImpl(Integer.toString(sourceGraphSize))));
// add digest graph size
int digestGraphSize = dataSet.getDigestGraph().size();
responseGraph.add(new TripleImpl(dataSet.getDigestGraphRef(), DLC.size, new PlainLiteralImpl(Integer.toString(digestGraphSize))));
// add enhance graph size
int enhanceGraphSize = dataSet.getEnhancementsGraph().size();
responseGraph.add(new TripleImpl(dataSet.getEnhancementsGraphRef(), DLC.size, new PlainLiteralImpl(Integer.toString(enhanceGraphSize))));
// add interlink graph size
int interlinkGraphSize = dataSet.getInterlinksGraph().size();
responseGraph.add(new TripleImpl(dataSet.getInterlinksGraphRef(), DLC.size, new PlainLiteralImpl(Integer.toString(interlinkGraphSize))));
// add smush graph size
int smushGraphSize = dataSet.getSmushGraph().size();
responseGraph.add(new TripleImpl(dataSet.getSmushGraphRef(), DLC.size, new PlainLiteralImpl(Integer.toString(smushGraphSize))));
// add publish graph size
int publishGraphSize = dataSet.getPublishGraph().size();
responseGraph.add(new TripleImpl(dataSet.getPublishGraphRef(), DLC.size, new PlainLiteralImpl(Integer.toString(publishGraphSize))));
}
}
/**
* Removes all the triples from the selected graph.
* @param uriInfo
* @param graphName
* @return
* @throws Exception
*/
@POST
@Path("clear_graph")
@Produces("text/plain")
public Response clearGraphRequest(@Context final UriInfo uriInfo,
@FormParam("graph") final String graphName) throws Exception {
AccessController.checkPermission(new AllPermission());
String message = "";
UriRef graphRef = new UriRef(graphName);
tcManager.getMGraph(graphRef).clear();
message += " Graph: " + graphName + " empty";
return RedirectUtil.createSeeOtherResponse("./", uriInfo);
//return message;
}
/**
* Removes the published triples from the content graph. More precisely the same triples stored in the publish.graph of a dataset
* will be removed from the content graph. Then all the triples in publish.graph are deleted so that data could be published again
* starting from smush.graph
*/
@POST
@Path("unpublish_dataset")
@Produces("text/plain")
public Response unpublishDataset(@Context final UriInfo uriInfo,
@FormParam("pipe") final UriRef pipeRef) {
final DataSet dataSet = dataSetFactory.getDataSet(pipeRef);
String message = "";
LockableMGraph publishGraph = dataSet.getPublishGraph();
int numberOfTriples = publishGraph.size();
if(numberOfTriples > 0) {
MGraph publishedTriples = new IndexedMGraph();
Lock pwl = publishGraph.getLock().readLock();
pwl.lock();
try {
publishedTriples.addAll(publishGraph);
}
finally {
pwl.unlock();
}
// remove published triples from content graph
LockableMGraph contentGraph = tcManager.getMGraph(new UriRef(SourcingAdmin.CONTENT_GRAPH_NAME));
contentGraph.removeAll(publishedTriples);
// removes all the triples in publish.graph
publishGraph.clear();
message += "All " + numberOfTriples + " triples have been removed from the content graph.";
}
else {
message += "There are no triples in " + pipeRef;
}
// update the dataset status (unpublished)
updateDatasetStatus(pipeRef);
return RedirectUtil.createSeeOtherResponse("./", uriInfo);
//return message;
}
/**
* Deletes all the graphs created with the pipe: rdf.graph, enhance.graph, interlink.graph, smush.graph, publish.graph.
* Removes from the DLC meta graph all the pipe metadata.
* @param uriInfo
* @param dataSetUri
* @return
* @throws Exception
*/
@POST
@Path("delete_pipe")
@Produces("text/plain")
public Response deletePipe(@Context final UriInfo uriInfo,
@FormParam("pipe") final UriRef dataSetUri) throws Exception {
AccessController.checkPermission(new AllPermission());
String message = "";
final DataSet dataSet = dataSetFactory.getDataSet(dataSetUri);
// remove graphs
tcManager.deleteTripleCollection(dataSet.getSourceGraphRef());
tcManager.deleteTripleCollection(dataSet.getDigestGraphRef());
tcManager.deleteTripleCollection(dataSet.getEnhancementsGraphRef());
tcManager.deleteTripleCollection(dataSet.getInterlinksGraphRef());
tcManager.deleteTripleCollection(dataSet.getSmushGraphRef());
tcManager.deleteTripleCollection(dataSet.getLogGraphRef());
LockableMGraph publishGraph = dataSet.getPublishGraph();
MGraph publishedTriples = new IndexedMGraph();
Lock pl = publishGraph.getLock().readLock();
pl.lock();
try {
publishedTriples.addAll(publishGraph);
}
finally {
pl.unlock();
}
tcManager.deleteTripleCollection(dataSet.getPublishGraphRef());
// remove pipe metadata
removePipeMetaData(dataSetUri);
message += "The dataset: " + dataSetUri + " has been deleted";
return RedirectUtil.createSeeOtherResponse("./", uriInfo);
//return message;
}
/**
* Updates the status of a dataset to unpublished
* @param pipeName
*/
private void updateDatasetStatus(final UriRef datasetUri) {
final LockableMGraph dlcGraph = dlcGraphProvider.getDlcGraph();
final UriRef statusRef = new UriRef(datasetUri.getUnicodeString() + "/Status");
dlcGraph.remove(new TripleImpl(statusRef, RDF.type, DLC.Published));
dlcGraph.remove(new TripleImpl(statusRef, RDFS.label, new PlainLiteralImpl("Published")));
dlcGraph.add(new TripleImpl(statusRef, RDF.type, DLC.Unpublished));
dlcGraph.add(new TripleImpl(statusRef, RDFS.label, new PlainLiteralImpl("Unpublished")));
}
/**
* Removes all the triples related to the pipe in the DLC graph: graphs and tasks metadata
* and pipe metadata.
* @param pipeRef
*/
private void removePipeMetaData(UriRef dataSetUri) {
final DataSet dataSet = dataSetFactory.getDataSet(dataSetUri);
// triple to remove
SimpleMGraph pipeGraph = new SimpleMGraph();
Lock rl = getDlcGraph().getLock().readLock();
rl.lock();
try {
// select source graph and rdf task metadata
UriRef rdfTaskRef = new UriRef(dataSetUri.getUnicodeString() + "/rdf");
UriRef sourceGraphRef = dataSet.getSmushGraphRef();
Iterator<Triple> isourceGraph = getDlcGraph().filter(sourceGraphRef, null, null);
while(isourceGraph.hasNext()) {
pipeGraph.add(isourceGraph.next());
}
Iterator<Triple> irdfTask = getDlcGraph().filter(rdfTaskRef, null, null);
while(irdfTask.hasNext()) {
pipeGraph.add(irdfTask.next());
}
// select digest graph and task metadata
UriRef digestTaskRef = new UriRef(dataSetUri.getUnicodeString() + "/digest");
UriRef digestGraphRef = dataSet.getDigestGraphRef();
Iterator<Triple> idigestGraph = getDlcGraph().filter(digestGraphRef, null, null);
while(idigestGraph.hasNext()) {
pipeGraph.add(idigestGraph.next());
}
Iterator<Triple> idigestTask = getDlcGraph().filter(digestTaskRef, null, null);
while(idigestTask.hasNext()) {
pipeGraph.add(idigestTask.next());
}
// select enhance graph and task metadata
UriRef enhanceTaskRef = new UriRef(dataSetUri.getUnicodeString() + "/enhance");
UriRef enhanceGraphRef = dataSet.getEnhancementsGraphRef();
Iterator<Triple> ienhanceGraph = getDlcGraph().filter(enhanceGraphRef, null, null);
while(ienhanceGraph.hasNext()) {
pipeGraph.add(ienhanceGraph.next());
}
Iterator<Triple> ienhanceTask = getDlcGraph().filter(enhanceTaskRef, null, null);
while(ienhanceTask.hasNext()) {
pipeGraph.add(ienhanceTask.next());
}
// select interlink graph and task metadata
UriRef interlinkTaskRef = new UriRef(dataSetUri.getUnicodeString() + "/interlink");
UriRef interlinkGraphRef = dataSet.getInterlinksGraphRef();
Iterator<Triple> iinterlinkGraph = getDlcGraph().filter(interlinkGraphRef, null, null);
while(iinterlinkGraph.hasNext()) {
pipeGraph.add(iinterlinkGraph.next());
}
Iterator<Triple> iinterlinkTask = getDlcGraph().filter(interlinkTaskRef, null, null);
while(iinterlinkTask.hasNext()) {
pipeGraph.add(iinterlinkTask.next());
}
// select smush graph and task metadata
UriRef smushTaskRef = new UriRef(dataSetUri.getUnicodeString() + "/smush");
UriRef smushGraphRef = dataSet.getSmushGraphRef();
Iterator<Triple> ismushGraph = getDlcGraph().filter(smushGraphRef, null, null);
while(ismushGraph.hasNext()) {
pipeGraph.add(ismushGraph.next());
}
Iterator<Triple> ismushTask = getDlcGraph().filter(smushTaskRef, null, null);
while(ismushTask.hasNext()) {
pipeGraph.add(ismushTask.next());
}
// select publish graph and task metadata
UriRef publishTaskRef = new UriRef(dataSetUri.getUnicodeString() + "/publish");
UriRef publishGraphRef = dataSet.getPublishGraphRef();
Iterator<Triple> ipublishGraph = getDlcGraph().filter(publishGraphRef, null, null);
while(ipublishGraph.hasNext()) {
pipeGraph.add(ipublishGraph.next());
}
Iterator<Triple> ipublishTask = getDlcGraph().filter(publishTaskRef, null, null);
while(ipublishTask.hasNext()) {
pipeGraph.add(ipublishTask.next());
}
// select dataset status
UriRef datasetStatusRef = new UriRef(dataSetUri.getUnicodeString() + "/Status");
Iterator<Triple> idatasetStatus = getDlcGraph().filter(datasetStatusRef, null, null);
while(idatasetStatus.hasNext()) {
pipeGraph.add(idatasetStatus.next());
}
// select pipe metadata
Iterator<Triple> ipipe = getDlcGraph().filter(dataSetUri, null, null);
while(ipipe.hasNext()) {
pipeGraph.add(ipipe.next());
}
}
finally {
rl.unlock();
}
getDlcGraph().removeAll(pipeGraph);
getDlcGraph().remove(new TripleImpl(dataSetUri, RDF.type, DLC.Pipe));
getDlcGraph().remove(new TripleImpl(DlcGraphProvider.DATA_LIFECYCLE_GRAPH_REFERENCE, DLC.pipe, dataSetUri));
}
/**
* Retrieves the selected graph.
* @param uriInfo
* @param graphName
* @return
* @throws Exception
*/
@GET
@Path("get_graph")
@Produces("text/plain")
public Response getGraphRequest(@Context final UriInfo uriInfo,
@QueryParam("graph") final String graphName) throws Exception {
String graphUrl = uriInfo.getBaseUri() + "graph?name=" + graphName;
return RedirectUtil.createSeeOtherResponse(graphUrl, uriInfo);
}
/**
* Returns the data life cycle graph containing all the monitored graphs. It
* creates it if doesn't exit yet.
*
* @return
*/
private LockableMGraph getDlcGraph() {
return tcManager.getMGraph(DlcGraphProvider.DATA_LIFECYCLE_GRAPH_REFERENCE);
}
@Activate
protected void activate(ComponentContext context) {
log.info("The Graphs Admin service is being activated");
}
@Deactivate
protected void deactivate(ComponentContext context) {
log.info("The Graphs Admin service is being deactivated");
}
}